﻿package net.wangit.view.page;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.wangit.Page;
import net.wangit.Unit;
import net.wangit.context.ActionContext;
import net.wangit.framework.config.DomainsSettings;
import net.wangit.framework.debug.Recorder;
import net.wangit.framework.util.InterceptorLoader;
import net.wangit.support.PageInterceptor;
import net.wangit.util.Checker;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitConfigurationException;
import net.wangit.view.unit.UnitFactory;
import net.wangit.view.unit.UnitWriter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class PageImpl implements Page, Cloneable {

	private static Log log = LogFactory
			.getLog(net.wangit.view.page.PageImpl.class);
	private String domain;
	private boolean supportLog;
	private int cacheMode;
	private List interceptorList;
	private Iterator interceptors;
	private String lastInterceptorName;
	private String id;
	private String template;
	private String windowTitle;
	private String head;
	private String cssPaths;
	private String headJsPaths;
	private String tailJsPaths;
	private String bodyAttribute;
	private String heading;
	private String subheading;
	private List<String> scripts;
	private Set<String> elementHeadJsPaths;
	private Set<String> elementTailJsPaths;
	private Set<String> elementCssPaths;
	private UnitComponent unit;
	private Map<String, String> attributes;

	public PageImpl() {
	}

	public void write(ActionContext ac) throws Exception {
		if (interceptors != null && interceptors.hasNext()) {
			PageInterceptor interceptor = (PageInterceptor) interceptors.next();
			if (Recorder.isEnabled()) {
				if (lastInterceptorName != null)
					Recorder.record((new StringBuilder("PI: ")).append(
							lastInterceptorName).toString());
				lastInterceptorName = interceptor.getClass().getName();
			}
			interceptor.intercept(ac, this);
		} else {
			if (Recorder.isEnabled() && lastInterceptorName != null)
				Recorder.record((new StringBuilder("PI: ")).append(
						lastInterceptorName).toString());
			writePage(ac);
		}
	}

	public String getDomain() {
		return domain;
	}

	private void writePage(ActionContext ac) throws Exception {
		UnitWriter writer = unit.getWriter();
		writer.writePage(ac, this);
	}

	public Page clonePage(ActionContext ac) {
		PageImpl page;
		try {
			page = (PageImpl) super.clone();
			page.cloneAfter(ac);
			return page;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	private void cloneAfter(ActionContext ac) {
		scripts = new ArrayList<String>();
		elementHeadJsPaths = new HashSet<String>();
		elementTailJsPaths = new HashSet<String>();
		elementCssPaths = new HashSet<String>();
		unit = UnitFactory.getUnit(ac, domain, id, this);
		attributes = new HashMap();
		interceptors = InterceptorLoader.getPageInterceptors(domain,
				interceptorList);
	}

	public UnitComponent getUnitComponent() {
		return unit;
	}

	protected void setId(String id) {
		this.id = id;
	}

	protected void setDomain(String domain) {
		this.domain = domain;
	}

	public int getCacheMode() {
		return cacheMode;
	}

	public String getHeading() {
		return heading;
	}

	public void setCacheMode(int cacheMode) {
		this.cacheMode = cacheMode;
	}

	protected void setInterceptors(String interceptors) {
		try {
			interceptorList = InterceptorLoader
					.loadPageInterceptors(interceptors);
		} catch (Exception e) {
			log.error((new StringBuilder("could not load page interceptors: "))
					.append(interceptors).toString(), e);
			throw new UnitConfigurationException((new StringBuilder(
					"could not load page interceptors: ")).append(interceptors)
					.toString(), domain, id, "page interceptors", e);
		}
	}

	public String getSubheading() {
		return subheading;
	}

	public String getTemplate() {
		return template;
	}

	public String getBodyAttribute() {
		return bodyAttribute;
	}

	public String getHead() {
		return head;
	}

	public String getCssPaths() {
		return cssPaths;
	}

	public String getHeadJsPaths() {
		return headJsPaths;
	}

	public String getTailJsPaths() {
		return tailJsPaths;
	}

	public String getWindowTitle() {
		if (Checker.isEmpty(windowTitle))
			return (new StringBuilder(String.valueOf(DomainsSettings
					.getWindowTitlePrefix(domain)))).append(
					DomainsSettings.getWindowTitleSuffix(domain)).toString();
		else
			return (new StringBuilder(String.valueOf(DomainsSettings
					.getWindowTitlePrefix(domain)))).append(windowTitle)
					.append(DomainsSettings.getWindowTitleSuffix(domain))
					.toString();
	}

	public boolean isSupportLog() {
		return supportLog;
	}

	public void setSupportLog(boolean supportLog) {
		this.supportLog = supportLog;
	}

	public void setHeading(String heading) {
		this.heading = heading;
	}

	public void setWindowTitle(String windowTitle) {
		this.windowTitle = windowTitle;
	}

	public void setSubheading(String subheading) {
		this.subheading = subheading;
	}

	public void setTemplate(String template) {
		this.template = template;
	}

	public Unit getUnit() {
		return unit;
	}

	public void setCssPaths(String cssPaths) {
		this.cssPaths = cssPaths;
	}

	public void setHeadJsPaths(String headJsPaths) {
		this.headJsPaths = headJsPaths;
	}

	public void setTailJsPaths(String tailJsPaths) {
		this.tailJsPaths = tailJsPaths;
	}

	public void setBodyAttribute(String bodyAttribute) {
		this.bodyAttribute = bodyAttribute;
	}

	public void setHead(String head) {
		this.head = head;
	}

	public Map<String, String> getAttributes() {
		return attributes;
	}

	public String getId() {
		return id;
	}

	public void addTailScript(String script) {
		scripts.add(script);
	}

	public List<String> getTailScripts() {
		return scripts;
	}

	public void putElementHeadJsPath(String jsPath) {
		elementHeadJsPaths.add(jsPath);
	}

	public void putElementHeadJsPath(Set<String> jsPaths) {
		elementHeadJsPaths.addAll(jsPaths);
	}

	public Set<String> getElementHeadJsPaths() {
		return elementHeadJsPaths;
	}

	public void putElementTailJsPath(String jsPath) {
		elementTailJsPaths.add(jsPath);
	}

	public void putElementTailJsPath(Set<String> jsPaths) {
		elementTailJsPaths.addAll(jsPaths);
	}

	public Set<String> getElementTailJsPaths() {
		return elementTailJsPaths;
	}

	public void putElementCssPath(String cssPath) {
		elementCssPaths.add(cssPath);
	}

	public void putElementCssPath(Set<String> cssPaths) {
		elementCssPaths.addAll(cssPaths);
	}

	public Set<String> getElementCssPaths() {
		return elementCssPaths;
	}

}
